﻿namespace ChinaUnicom.Storage
{
    using Avatar.Log;
    using Newtonsoft.Json;
    using System;
    using System.IO;
    using System.IO.IsolatedStorage;

    public sealed class JsonStorage
    {
        public static T Restore<T>(string key = null)
        {
            if (string.IsNullOrEmpty(key))
            {
                return new JsonStorage().ReadTypeData<T>();
            }

            return new JsonStorage().ReadFromKey<T>(key);
        }

        public static void Store<T>(T obj, string key = null)
        {
            if (string.IsNullOrEmpty(key))
            {
                new JsonStorage().WriteTypeData(obj);
            }
            else
            {
                new JsonStorage().WriteWithKey(obj, key);
            }
        }

        public static void Remove<T>()
        {
            new JsonStorage().DeleteFile(typeof(T));
        }

        public static void Remove(string key)
        {
            new JsonStorage().DeleteFile(key);
        }

        private JsonStorage() { }

        #region members

        IsolatedStorageFile storage
        {
            get { return IsolatedStorageFile.GetUserStoreForApplication(); }
        }

        T ReadTypeData<T>()
        {
            Type type = typeof(T);
            return ReadFromKey<T>(GetPath(type));
        }

        T ReadFromKey<T>(string key)
        {
            try
            {
                Type type = typeof(T);
                using (var fs = storage.OpenFile(key, FileMode.OpenOrCreate))
                using (StreamReader sr = new StreamReader(fs))
                {
                    JsonSerializer s = new JsonSerializer();
                    return s.Deserialize<T>(new JsonTextReader(sr));
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                throw;
            }
        }

        void WriteTypeData<T>(T obj)
        {
            Type type = obj.GetType();
            WriteWithKey(obj, GetPath(type));
        }

        void WriteWithKey(object obj, string key)
        {
            try
            {
                using (var fs = storage.OpenFile(key, FileMode.OpenOrCreate))
                using (StreamWriter sw = new StreamWriter(fs))
                {
                    JsonSerializer s = new JsonSerializer();
                    s.Serialize(sw, obj);
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                throw;
            }
        }

        void DeleteFile(string path)
        {
            if (storage.FileExists(path))
            {
                try
                {
                    storage.DeleteFile(path);
                }
                catch (Exception ex)
                {
                    Logger.Error(ex);
                    throw;
                }
            }
        }

        void DeleteFile(Type type)
        {
            DeleteFile(GetPath(type));
        }

        string GetPath(Type type)
        {
            return string.Format("{0}.json", type.FullName.ToLower());
        }

        #endregion
    }
}
